package cc.rengu.igas.share.core.service.asyncall;

import cc.rengu.igas.acct.facade.result.Result;
import cc.rengu.igas.channel.ncqs.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.upac.facade.bean.CustomerInfo;
import cc.rengu.igas.channel.upac.facade.bean.TokenPayInfo;
import cc.rengu.igas.channel.upac.facade.request.TokenPayOpenByOrderIdRequest;
import cc.rengu.igas.channel.upac.facade.response.TokenPayOpenByOrderIdResponse;
import cc.rengu.igas.share.common.enums.SignTypeEnum;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.DubboAsynBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.annotation.BIZ_PROCESS;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.List;

/**
 * 无跳转签约并支付异步处理
 */
public class AsynUpacTokenApplyService extends DubboAsynBaseService {

    @BIZ_PROCESS
    public void upacTokenApply() throws Exception {

        rglog.debug("无跳转异步处理类-AsynUpacTokenApplyService");
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        if (!xmlTreeUtil.isExist("tokenPayOpenByOrderIdRequest")) {
            return;
        }
        TokenPayOpenByOrderIdRequest tokenPayOpenByOrderIdRequest = (TokenPayOpenByOrderIdRequest) xmlTreeUtil.getXmlTreeObjectValue("tokenPayOpenByOrderIdRequest", TokenPayOpenByOrderIdRequest.class);

        /*查询商户支付订单列表*/
        MchntOrderInfoMapper opmsMchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> mchntOrderInfoList = opmsMchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(instId, tokenPayOpenByOrderIdRequest.getOrderId());
        if (null == mchntOrderInfoList || 0 == mchntOrderInfoList.size()) {
            rglog.info("商户订单信息表中无该笔商户支付订单,instId:<{}>,sysSeqNum:<{}>.", instId, tokenPayOpenByOrderIdRequest.getOrderId());
            return;
        }

        /*获取支付订单列表*/
        PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
        List<PayOrderInfo> payOrderInfoList = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(instId, tokenPayOpenByOrderIdRequest.getOrderId());
        if (payOrderInfoList == null || payOrderInfoList.isEmpty()) {
            rglog.error("根据机构号<{}>、系统流水号<{}>获取支付订单列表失败", instId, tokenPayOpenByOrderIdRequest.getOrderId());
            return;
        }

        /*判断记账结果，更新支付订单状态*/
        if (!xmlTreeUtil.isExist(TreeNodeConstant.DUBBO_RESPONSE)) {
            rglog.error("dubbo调用失败");
            return;
        }
        rglog.debug("dubbo调用正常返回");
        String responseStr = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.DUBBO_RESPONSE);
        Result<JSONObject> responseResult = (Result<JSONObject>) xmlTreeUtil.getXmlTreeObjectValue(TreeNodeConstant.DUBBO_RESPONSE, Result.class);
        if (!responseResult.isSuccess()) {
            rglog.error("dubbo调用失败");
            return;
        }

        //获取token查询结果
        TokenPayOpenByOrderIdResponse response = JSON.toJavaObject(responseResult.getResult(), TokenPayOpenByOrderIdResponse.class);
        rglog.info("token查询结果:<{}>", JSON.toJSONString(response));
        if (!OltpRpcdEnum.TRANS_SUCCESS.getRespCode().equals(response.getRespCode()) || !"1".equals(response.getActivateStatus())) {
            rglog.error("业务处理失败respCode<{}>,respDesc<{}>", response.getRespCode(), response.getRespDesc());
            return;
        }

        //根据银联订单号查询签约信息表
        rglog.debug("流程日志-根据银联订单号查询签约信息表...");
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        SignAcctInfo signAcctInfo = signAcctInfoMapper.selectSignAcctInfoBySignSeqNum(tokenPayOpenByOrderIdRequest.getHeader().getInstId(), tokenPayOpenByOrderIdRequest.getOrderId());
        if (null == signAcctInfo) {
            rglog.info("原全渠道签约申请交易不存在");
            return;
        }

        //判断原交易是签约并支付 或 首次签约并支付
        rglog.debug("流程日志-判断原交易是签约并支付或首次签约并支付.bizType:<{}>", mchntOrderInfoList.get(0).getBizType());
        if ("00".equals(mchntOrderInfoList.get(0).getBizType())) {
            rglog.info("登记用户订单表....");
            registUserInfo(mchntOrderInfoList, signAcctInfo, response);
        }

        //更新签约信息表
        rglog.info("更新签约信息表....");
        signAcctInfo = updateSignInfo(signAcctInfo, response);
        if (0 != signAcctInfoMapper.updateSignAcctInfoBySignAcctNo(signAcctInfo)) {
            rglog.error("更新签约信息表失败,signAcctInfo:<{}>", JSONObject.toJSONString(signAcctInfo));
        } else {
            rglog.debug("更新签约信息表成功,signAcctInfo:<{}>", JSONObject.toJSONString(signAcctInfo));
        }
    }

    /**
     * 登记收银台用户信息表
     *
     * @param mchntOrderInfoList            商户订单
     * @param signAcctInfo                  签约关系
     * @param tokenPayOpenByOrderIdResponse token响应体
     * @throws Exception 异常
     */
    private void registUserInfo(List<MchntOrderInfo> mchntOrderInfoList, SignAcctInfo signAcctInfo, TokenPayOpenByOrderIdResponse tokenPayOpenByOrderIdResponse) {

        try {
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);

            MchntService mchntService = new MchntServiceImpl();
            MchntInfo mchntInfo = mchntService.getMchntInfo(mchntOrderInfoList.get(0).getInstId(), mchntOrderInfoList.get(0).getMchntNo());
            if (null == mchntInfo) {
                rglog.error("查询商户基本信息失败<{}>", mchntOrderInfoList.get(0).getMchntNo());
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            String signType = mchntInfo.getMchntSignType();

            String instId = mchntOrderInfoList.get(0).getInstId();
            String userInst;
            rglog.info("用户主体和签约主体保持一致，根据商户签约类型进行判断。商户签约类型为:<{}>", signType);
            if (SignTypeEnum.BANK_CLASS_SIGN.getSignTypeCode().equals(signType)) {
                rglog.debug("商户签约级别为机构级签约，用户主体及签约主体都是法人机构号:<{}>", instId);
                userInst = instId;
            } else if (SignTypeEnum.PLAT_CLASS_SIGN.getSignTypeCode().equals(signType)) {
                rglog.debug("商户签约级别为平台级签约，用户主体及签约主体都是平台商户号:<{}>", mchntInfo.getPlatMchntNo());
                userInst = mchntInfo.getPlatMchntNo();
            } else if (SignTypeEnum.MCHNT_CLASS_SIGN.getSignTypeCode().equals(signType)) {
                rglog.debug("商户签约级别为机构级签约，用户主体及签约主体都是平台商户号:<{}>", mchntInfo.getMchntNo());
                userInst = mchntInfo.getMchntNo();
            } else {
                rglog.error("无法识别的签约级别:<{}>,不处理", signType);
                return;
            }

            //登记用户信息表
            CustomerInfo customerInfo = tokenPayOpenByOrderIdResponse.getCustomerInfo();
            UserInfo userInfo = new UserInfo();
            userInfo.setInstId(tokenPayOpenByOrderIdResponse.getHeader().getInstId());
            //加密盐值 生成规则：当前机构号+时间戳+6位随机数
            userInfo.setTransPasswordSalt(tokenPayOpenByOrderIdResponse.getHeader().getInstId() + DateUtil.getCurrentDate() + sysSeqNum.substring(sysSeqNum.length() - 8));
            userInfo.setUserInst(userInst);
            userInfo.setUserId(signAcctInfo.getUserId());
            userInfo.setUserName(customerInfo.getCustName());
            userInfo.setMobileNo(customerInfo.getPhoneNo());
            userInfo.setCertType(StringUtil.isEmptyOrNull(customerInfo.getCertType()) ? signAcctInfo.getCertType() : customerInfo.getCertType());
            userInfo.setCertNo(StringUtil.isEmptyOrNull(customerInfo.getCertNo()) ? signAcctInfo.getCertNo() : customerInfo.getCertNo());

            UserService userService = new UserServiceImpl();
            boolean registerFlag = userService.registerUserInfo(userInfo);
            if (!registerFlag) {
                rglog.info("登记收银台用户信息表失败:<{}>", JSON.toJSONString(userInfo));
            }
        } catch (Exception e) {
            rglog.error("登记收银台用户信息表异常:<{}>", e);
            throw new BizException(OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode(), OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
        }
    }

    /**
     * 更新签约信息表
     *
     * @param signAcctInfo                  签约实体
     * @param tokenPayOpenByOrderIdResponse 响应实体
     * @throws Exception 异常
     */
    private SignAcctInfo updateSignInfo(SignAcctInfo signAcctInfo, TokenPayOpenByOrderIdResponse tokenPayOpenByOrderIdResponse) {

        CustomerInfo customerInfo = tokenPayOpenByOrderIdResponse.getCustomerInfo();
        TokenPayInfo tokenPayInfo = tokenPayOpenByOrderIdResponse.getTokenPayInfo();
        //联行行号
        String branchNo = signAcctInfo.getSignToken().split("\\|")[0];
        //更新签约数据
        signAcctInfo.setSignToken(branchNo + "|" + tokenPayInfo.getToken());
        signAcctInfo.setReserveMobileNo(customerInfo.getPhoneNo());
        signAcctInfo.setSignExpiryDate(tokenPayInfo.getTokenEnd().substring(0, 8));
        signAcctInfo.setSignStatus(AppParamConstant.YES);
        return signAcctInfo;
    }

}
